<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>src/node/class.particles.js - sceneGraph.js</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.9.1/build/cssgrids/cssgrids-min.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
    <link rel="shortcut icon" type="image/png" href="../assets/favicon.png">
    <script src="http://yui.yahooapis.com/combo?3.9.1/build/yui/yui-min.js"></script>
</head>
<body class="yui3-skin-sam">

<div id="doc">
    <div id="hd" class="yui3-g header">
        <div class="yui3-u-3-4">
            
                <h1><img src="../../logo/logoCGSG_256x57.png" title="sceneGraph.js"></h1>
            
        </div>
        <div class="yui3-u-1-4 version">
            <em>API Docs for: v2.1.0</em>
        </div>
    </div>
    <div id="bd" class="yui3-g">

        <div class="yui3-u-1-4">
            <div id="docs-sidebar" class="sidebar apidocs">
                <div id="api-list">
    <h2 class="off-left">APIs</h2>
    <div id="api-tabview" class="tabview">
        <ul class="tabs">
            <li><a href="#api-classes">Classes</a></li>
            <li><a href="#api-modules">Modules</a></li>
        </ul>

        <div id="api-tabview-filter">
            <input type="search" id="api-filter" placeholder="Type to filter APIs">
        </div>

        <div id="api-tabview-panel">
            <ul id="api-classes" class="apis classes">
            
                <li><a href="../classes/CGSG.html">CGSG</a></li>
            
                <li><a href="../classes/CGSGAccordion.html">CGSGAccordion</a></li>
            
                <li><a href="../classes/CGSGAnimationManager.html">CGSGAnimationManager</a></li>
            
                <li><a href="../classes/CGSGAnimationMethod.html">CGSGAnimationMethod</a></li>
            
                <li><a href="../classes/CGSGBindEntry.html">CGSGBindEntry</a></li>
            
                <li><a href="../classes/CGSGButtonMode.html">CGSGButtonMode</a></li>
            
                <li><a href="../classes/CGSGCollisionGhostOnDemandTester.html">CGSGCollisionGhostOnDemandTester</a></li>
            
                <li><a href="../classes/CGSGCollisionManager.html">CGSGCollisionManager</a></li>
            
                <li><a href="../classes/CGSGCollisionMethod.html">CGSGCollisionMethod</a></li>
            
                <li><a href="../classes/CGSGCollisionRegionTester.html">CGSGCollisionRegionTester</a></li>
            
                <li><a href="../classes/CGSGCollisionTesterFactory.html">CGSGCollisionTesterFactory</a></li>
            
                <li><a href="../classes/CGSGColor.html">CGSGColor</a></li>
            
                <li><a href="../classes/CGSGCSSManager.html">CGSGCSSManager</a></li>
            
                <li><a href="../classes/CGSGDimension.html">CGSGDimension</a></li>
            
                <li><a href="../classes/CGSGEvent.html">CGSGEvent</a></li>
            
                <li><a href="../classes/CGSGEventManager.html">CGSGEventManager</a></li>
            
                <li><a href="../classes/CGSGHandleBox.html">CGSGHandleBox</a></li>
            
                <li><a href="../classes/CGSGImgManager.html">CGSGImgManager</a></li>
            
                <li><a href="../classes/CGSGInterpolator.html">CGSGInterpolator</a></li>
            
                <li><a href="../classes/CGSGInterpolatorLinear.html">CGSGInterpolatorLinear</a></li>
            
                <li><a href="../classes/CGSGInterpolatorTCB.html">CGSGInterpolatorTCB</a></li>
            
                <li><a href="../classes/CGSGKeyFrame.html">CGSGKeyFrame</a></li>
            
                <li><a href="../classes/CGSGMap.html">CGSGMap</a></li>
            
                <li><a href="../classes/CGSGMask.html">CGSGMask</a></li>
            
                <li><a href="../classes/CGSGMaskCache.html">CGSGMaskCache</a></li>
            
                <li><a href="../classes/CGSGMaskClip.html">CGSGMaskClip</a></li>
            
                <li><a href="../classes/CGSGMath.html">CGSGMath</a></li>
            
                <li><a href="../classes/CGSGNode.html">CGSGNode</a></li>
            
                <li><a href="../classes/CGSGNodeButton.html">CGSGNodeButton</a></li>
            
                <li><a href="../classes/CGSGNodeCircle.html">CGSGNodeCircle</a></li>
            
                <li><a href="../classes/CGSGNodeColorPicker.html">CGSGNodeColorPicker</a></li>
            
                <li><a href="../classes/CGSGNodeCurveTCB.html">CGSGNodeCurveTCB</a></li>
            
                <li><a href="../classes/CGSGNodeDomElement.html">CGSGNodeDomElement</a></li>
            
                <li><a href="../classes/CGSGNodeEllipse.html">CGSGNodeEllipse</a></li>
            
                <li><a href="../classes/CGSGNodeImage.html">CGSGNodeImage</a></li>
            
                <li><a href="../classes/CGSGNodeLine.html">CGSGNodeLine</a></li>
            
                <li><a href="../classes/CGSGNodeSlider.html">CGSGNodeSlider</a></li>
            
                <li><a href="../classes/CGSGNodeSliderHandle.html">CGSGNodeSliderHandle</a></li>
            
                <li><a href="../classes/CGSGNodeSprite.html">CGSGNodeSprite</a></li>
            
                <li><a href="../classes/CGSGNodeSquare.html">CGSGNodeSquare</a></li>
            
                <li><a href="../classes/CGSGNodeTabMenu.html">CGSGNodeTabMenu</a></li>
            
                <li><a href="../classes/CGSGNodeText.html">CGSGNodeText</a></li>
            
                <li><a href="../classes/CGSGNodeWebview.html">CGSGNodeWebview</a></li>
            
                <li><a href="../classes/CGSGParticle.html">CGSGParticle</a></li>
            
                <li><a href="../classes/CGSGParticleEmitter.html">CGSGParticleEmitter</a></li>
            
                <li><a href="../classes/CGSGParticleSystem.html">CGSGParticleSystem</a></li>
            
                <li><a href="../classes/CGSGPickNodeMethod.html">CGSGPickNodeMethod</a></li>
            
                <li><a href="../classes/CGSGPosition.html">CGSGPosition</a></li>
            
                <li><a href="../classes/CGSGRegion.html">CGSGRegion</a></li>
            
                <li><a href="../classes/CGSGRotation.html">CGSGRotation</a></li>
            
                <li><a href="../classes/CGSGScale.html">CGSGScale</a></li>
            
                <li><a href="../classes/CGSGSceneGraph.html">CGSGSceneGraph</a></li>
            
                <li><a href="../classes/CGSGSection.html">CGSGSection</a></li>
            
                <li><a href="../classes/CGSGTimeline.html">CGSGTimeline</a></li>
            
                <li><a href="../classes/CGSGTraverser.html">CGSGTraverser</a></li>
            
                <li><a href="../classes/CGSGVector2D.html">CGSGVector2D</a></li>
            
                <li><a href="../classes/CGSGView.html">CGSGView</a></li>
            
                <li><a href="../classes/CGSGWEBVIEWMODE.html">CGSGWEBVIEWMODE</a></li>
            
                <li><a href="../classes/CGSGWrapMode.html">CGSGWrapMode</a></li>
            
                <li><a href="../classes/GLOBAL_CONSTANTS.html">GLOBAL_CONSTANTS</a></li>
            
                <li><a href="../classes/GLOBAL_METHODS.html">GLOBAL_METHODS</a></li>
            
                <li><a href="../classes/GLOBAL_PROPERTIES.html">GLOBAL_PROPERTIES</a></li>
            
                <li><a href="../classes/UTIL_ARRAY.html">UTIL_ARRAY</a></li>
            
                <li><a href="../classes/WUICCGSGNodeImageFactory.html">WUICCGSGNodeImageFactory</a></li>
            
            </ul>

            <ul id="api-modules" class="apis modules">
            
                <li><a href="../modules/Animation.html">Animation</a></li>
            
                <li><a href="../modules/Collision.html">Collision</a></li>
            
                <li><a href="../modules/Math.html">Math</a></li>
            
                <li><a href="../modules/Node.html">Node</a></li>
            
                <li><a href="../modules/ParticleSystem.html">ParticleSystem</a></li>
            
                <li><a href="../modules/Scene.html">Scene</a></li>
            
                <li><a href="../modules/Util.html">Util</a></li>
            
            </ul>
        </div>
    </div>
</div>

            </div>
        </div>
        <div class="yui3-u-3-4">
                <div id="api-options">
        Show:
        <label for="api-show-inherited">
            <input type="checkbox" id="api-show-inherited" checked>
            Inherited
        </label>

        <label for="api-show-protected">
            <input type="checkbox" id="api-show-protected">
            Protected
        </label>

        <label for="api-show-private">
            <input type="checkbox" id="api-show-private">
            Private
        </label>
        <label for="api-show-deprecated">
            <input type="checkbox" id="api-show-deprecated">
            Deprecated
        </label>

    </div>


            <div class="apidocs">
                <div id="docs-main">
                    <div class="content">
                        <h1 class="file-heading">File: src/node/class.particles.js</h1>

<div class="file">
    <pre class="code prettyprint linenums">
/*
 * Copyright (c) 2014 Gwennael Buchet
 *
 * License/Terms of Use
 *
 * Permission is hereby granted, free of charge and for the term of intellectual property rights on the Software, to any
 * person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to use, copy, modify
 * and propagate free of charge, anywhere in the world, all or part of the Software subject to the following mandatory
 * conditions:
 *
 *   •    The above copyright notice and this permission notice shall be included in all copies or substantial portions
 *   of the Software.
 *
 *  Any failure to comply with the above shall automatically terminate the license and be construed as a breach of these
 *  Terms of Use causing significant harm to Gwennael Buchet.
 *
 *  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 *  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 *  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 *  Except as contained in this notice, the name of Gwennael Buchet shall not be used in advertising or otherwise to promote
 *  the use or other dealings in this Software without prior written authorization from Gwennael Buchet.
 *
 *  These Terms of Use are subject to French law.
 */

&quot;use strict&quot;;

/**
 * @module Animation
 * @submodule ParticleSystem
 * @class CGSGParticle
 * @constructor
 * @param node {CGSGNode}
 * @type {CGSGParticle}
 * @author Gwennael Buchet (gwennael.buchet@gmail.com)
 */
var CGSGParticle = CGSGObject.extend(
    {
        initialize: function (node) {
            /**
             * @property node
             * @type {CGSGNode}
             */
            this.node = node;

            this.node.isClickable = false;
            this.node.isResizable = false;
            this.node.isDraggable = false;

            /**
             * A void* property to let the developer store whatever he needs (new properties, ...)
             * @property userData
             * @type {*}
             * @default null
             */
            this.userData = null;

            this.init();
        },

        /**
         * Initialize attributes of this particle
         * @public
         * @method init
         */
        init: function () {
            //this.direction = new CGSGVector2D(1, 0);
            this.position = new CGSGPosition(0.0, 0.0);
            this.mass = 1000;
            this.initVelocity(new CGSGVector2D(1.0, 1.0));
            this.checkCTL = null;
            this.isAlive = true;
            this.age = 0;

            //this._gravity = new CGSGVector2D(0.0, 0.0);
            //this._forceTotal = new CGSGVector2D(0.0, 0.0);
            this._acceleration = new CGSGVector2D(0.0, 0.0);

            this.speedThreshold = 0.0;
        },

        /**
         * @public
         * @method initPosition
         * @param {Number} x
         * @param {Number} y
         */
        initPosition: function (x, y) {
            this.position.x = x;
            this.position.y = y;
            this.node.translateTo(x, y);
        },

        /**
         * @public
         * @method initVelocity
         * @param {CGSGVector2D} velocity
         */
        initVelocity: function (velocity) {
            this.velocity = velocity.copy();
            this.velocity.normalize();
        },

        /**
         * @public
         * @method initSpeedThreshold
         * @param {Number} st
         */
        initSpeedThreshold: function (st) {
            this.speedThreshold = st;
        },

        /**
         * update the particle position with an Euler integration
         * TODO : externalize the process to choose between RK4 and Euler integration
         * @public
         * @method updatePosition
         * @param {Number} deltaTime
         * @param {Number} acceleration
         * @return {*}
         */
        updatePosition: function (deltaTime, acceleration) {
            if (isNaN(deltaTime)) {
                deltaTime = 1.0;
            }

            deltaTime += this.speedThreshold;

            this._acceleration.x = acceleration.x / this.mass;
            this._acceleration.y = acceleration.y / this.mass;

            this.velocity.x += this._acceleration.x * deltaTime;
            this.velocity.y += this._acceleration.y * deltaTime;

            this.position.x += this.velocity.x * deltaTime;
            this.position.y += this.velocity.y * deltaTime;

            if (this.node !== null) {
                this.node.translateTo(this.position.x, this.position.y);
            }

            //increment age of the particle
            this.age += deltaTime;

            //check the viablity of the particle
            if (cgsgExist(this.checkCTL)) {
                this.isAlive = this.checkCTL(this);
            }
            return this.isAlive;
        }
    }
);

/**
 * A particle emitter for the cgSceneGraph Particle System
 * @class CGSGParticleEmitter
 * @extends {CGSGNode}
 * @module Animation
 * @submodule ParticleSystem
 * @constructor
 * @param {Function} nodeConstructor
 * @param {CGSGRegion} region
 * @param {Number} nbParticlesMax
 * @param {Number} velocity
 * @param {Number} angle
 * @param {Number} speed
 * @param {Number} speedThreshold
 * @param {Number} outflow
 * @type {CGSGParticleEmitter}
 * @author Gwennael Buchet (gwennael.buchet@gmail.com)
 */
var CGSGParticleEmitter = CGSGNode.extend(
    {
        initialize: function (nodeConstructor, region, nbParticlesMax, velocity, angle, speed, speedThreshold,
                              outflow) {
            this._super(region.position.x, region.position.y);
            this.resizeTo(region.dimension.width, region.dimension.height);

            /**
             * @property classType
             * @type {String}
             */
            this.classType = &quot;CGSGParticleEmitter&quot;;

            this._nodeContructor = nodeConstructor;
            /**
             * the region from where the particles are emitted
             * @property region
             * @type {CGSGRegion}
             */
            this.region = region;
            /**
             * number max of particles out of the emitter on 1 frame
             * @property nbParticlesMax
             * @type {Number}
             */
            this.nbParticlesMax = nbParticlesMax;
            /**
             * @property velocity
             * @type {CGSGVector2D}
             */
            this.velocity = new CGSGVector2D(0.0, 0.0);
            if (cgsgExist(velocity)) {
                this.velocity = velocity;
            }
            /**
             * angle range of emission. a particle is emitted in the this.direction vector + or - this.angle/2 angle.
             * @property angle
             * @type {Number}
             */
            this.angle = Math.PI / 5.0;
            if (cgsgExist(angle)) {
                this.angle = angle;
            }

            /**
             * speed of a particle
             * @property speed
             * @type {Number}
             */
            this.speed = 1.0;
            if (cgsgExist(speed)) {
                this.speed = speed;
            }
            /**
             * threshold to randomize and add to the speed of a particle
             * @property speedThreshold
             * @type {Number}
             */
            this.speedThreshold = 1.0;
            if (cgsgExist(speedThreshold)) {
                this.speedThreshold = speedThreshold;
            }

            /**
             * @property outflow
             * @type {Number}
             */
            this.outflow = 0;
            if (cgsgExist(outflow)) {
                this.outflow = outflow;
            }

            this._currentFrame = this.outflow;

            //list of the particles
            this._particles = [];
            this._isPlaying = false;
            this._forces = [];
            this._acceleration = new CGSGVector2D(0.0, 0.0);

            /**
             * Gravity Force added by default with the addForce method
             * @property gravity
             * @type {Object}
             */
            this.gravity = this.addForce(new CGSGVector2D(0.0, 9.81), null);

            /**
             * Callback on end of update for 1 particle
             * @property onUpdateParticleEnd
             * @default null
             * @type {function}
             */
            this.onUpdateParticleEnd = null;
            /**
             * Callback when reinit for 1 particle
             * @property onInitParticle
             * @default null
             * @type {function}
             */
            this.onInitParticle = null;
            /**
             * Callback when reinit all particles is done
             * @property onInitParticlesEnd
             * @default null
             * @type {function}
             */
            this.onInitParticlesEnd = null;
        },

        /**
         * start the animation
         * @public
         * @method start
         */
        start: function () {
            this._isPlaying = true;
        },

        /**
         * stop the animation
         * @public
         * @method stop
         */
        stop: function () {
            this._isPlaying = false;
        },

        /**
         * reset the animation
         * @public
         * @method reset
         */
        reset: function () {
            var p;
            this._currentFrame = 0;
            //free the memory
            for (p = this._particles.length - 1; p &gt;= 0; p--) {
                this.removeChild(this._particles[p].node, true);
                delete (this._particles[p]);
            }
            this._particles.clear();
        },

        /**
         * @public
         * @method render
         * @param context
         */
        render: function (context) {
            var f, p;
            this.beforeRender(context);

            //update the acceleration of the particles, based on the current forces
            this._acceleration.initialize(0.0, 0.0);
            for (f = this._forces.length - 1; f &gt;= 0; f--) {
                this._acceleration.x += this._forces[f].vector.x;
                this._acceleration.y += this._forces[f].vector.y;

                if (this._forces[f].ctl !== null) {
                    this._forces[f].age++;
                    if (this._forces[f].age &gt;= this._forces[f].ctl) {
                        this.removeForce(this._forces[f]);
                    }
                }
            }

            //updates all particles
            for (p = 0; p &lt; this._particles.length; p++) {
                if (this._isPlaying) {
                    if (!this._particles[p].isAlive || !this.updateParticle(this._particles[p])) {
                        this.initParticle(this._particles[p], p);
                    }
                }

                this._particles[p].node.render(context);
            }

            //if not all of the particles are out
            if (this._particles.length &lt; this.nbParticlesMax) {
                this._currentFrame++;
                if (this._currentFrame &gt;= this.outflow) {
                    this._currentFrame = 0;
                    this._createParticle(this._particles.length);
                }
            }

            //restore state
            //this.afterRender(context);
            context.restore();
        },

        /**
         * create a new particle, and add it to the emitter
         * @private
         * @method _createParticle
         * @param {Number} index
         */
        _createParticle: function (index) {
            var node = this._nodeContructor();
            var particle = new CGSGParticle(node);
            this.initParticle(particle, index);
            this.addChild(particle.node);
            this._particles.push(particle);
        },

        /**
         * @public
         * @method initParticle
         * @param {CGSGParticle} particle
         * @param {Number} index
         */
        initParticle: function (particle, index) {
            particle.init();
            //set a random position inside the region of this emitter
            particle.initPosition(Math.random() * this.region.dimension.width,
                                  Math.random() * this.region.dimension.height);

            //set a random direction inside the angle
            var velocity = this.velocity.copy();
            var halfAngle = this.angle / 2.0;
            velocity.rotate(-halfAngle + Math.random() * this.angle);
            particle.initVelocity(velocity);

            particle.initSpeedThreshold(-this.speedThreshold + Math.random() * this.speedThreshold * 2.0);

            if (this.onInitParticle !== null) {
                CGSG.eventManager.dispatch(this, cgsgEventTypes.ON_INIT_PARTICLE,
                                           new CGSGEvent(this, {index: index, particle: particle}));
                //this.onInitParticle({index : index, particle : particle});
                //this.onInitParticle({data :{index : index, particle : particle}});
            }
        },

        /**
         * @public
         * @method updateParticle
         * @param {CGSGParticle} particle
         * @return {Boolean}
         */
        updateParticle: function (particle) {
            //first, update the position of the particle node
            var isAlive = particle.updatePosition(this.speed, this._acceleration);

            //finally, call the update method of the particle node to apply extra animations
            //if (this.onUpdateParticleEnd !== null) {
            this.onUpdateParticleEnd &amp;&amp;
            CGSG.eventManager.dispatch(this, cgsgEventTypes.ON_UPDATE_PARTICLE_END,
                                       new CGSGEvent(this, {particle: particle}));
            //this.onUpdateParticleEnd(particle);
            //this.onUpdateParticleEnd({data:{particle : particle}});
            //}

            return isAlive;
        },

        /**
         * Add a force to the emitter
         * @public
         * @method addForce
         * @param {CGSGVector2D} vector
         * @param {Number} ttl time to live of the force
         * @return {Object}
         */
        addForce: function (vector, ttl) {
            var force = {vector: vector, ctl: ttl, age: 0};
            this._forces.push(force);
            return force;
        },

        /**
         * Remove a previously added force
         * @public
         * @method removeForce
         * @param {Object} force
         */
        removeForce: function (force) {
            this._forces.without(force);
        }/*,

     addImpulse : function(point, force, ttl) {
     for (var p = 0; p &lt; this._particles.length; p++) {
     this._particles[p].addImpulse(point, force, ttl);
     }
     }*/
    }
);

/**
 * A particle System object.
 * @class CGSGParticleSystem
 * @extends {CGSGNode}
 * @module Animation
 * @submodule ParticleSystem
 * @type {CGSGParticleSystem}
 * @author Gwennael Buchet (gwennael.buchet@gmail.com)
 */
var CGSGParticleSystem = CGSGNode.extend(
    {
        initialize: function (x, y) {
            this._super(x, y);

            /**
             * @property classType
             * @type {String}
             */
            this.classType = &quot;CGSGParticleSystem&quot;;

            /**
             * list of emitters
             * @property emitters
             * @type {Array}
             */
            this.emitters = [];
            /**
             * list of attractors
             * @property attractors
             * @type {Array}
             */
            this.attractors = [];
            /**
             * list of repulsors
             * @property repulsors
             * @type {Array}
             */
            this.repulsors = [];

            this.isClickable = false;
            this.isResizable = false;
            this.isDraggable = false;
            this.isTraversable = false;

            //factory pattern
            //this.integrator = new CGSGParticleIntegratorEuler();
            //this.integrator = new CGSGParticleIntegratorRK4();
        },

        /**
         * Add a force to all emitters
         * @public
         * @method addForce
         * @param {CGSGVector2D} vector
         */
        addForce: function (vector) {
            for (var e = 0; e &lt; this.emitters.length; e++) {
                this.emitters[e].addForce(vector);
            }
        },

        /*addImpulse : function(point, force, ttl) {
         for (var e = 0; e &lt; this.emitters.length; e++) {
         this.emitters[e].addImpulse(point, force, ttl);
         }
         },*/

        /**
         * Create a new emitter and return it
         * @public
         * @method addEmitter
         * @param {CGSGNode} node
         * @param {CGSGRegion} region
         * @param {Number} nbParticlesMax
         * @param {Number} velocity
         * @param {Number} angle
         * @param {Number} speed
         * @param {Number} speedThreshold
         * @param {Number} outflow
         * @return {CGSGParticleEmitter}
         */
        addEmitter: function (node, region, nbParticlesMax, velocity, angle, speed, speedThreshold, outflow) {
            var emitter = new CGSGParticleEmitter(node, region, nbParticlesMax, velocity, angle, speed, speedThreshold,
                                                  outflow);
            this.addChild(emitter);
            this.emitters.push(emitter);
            return emitter;
        },

        /**
         * Remove the emitter passed in parameter
         * @public
         * @method removeEmitter
         * @param {CGSGParticleEmitter} emitter
         */
        removeEmitter: function (emitter) {
            this.emitters.without(emitter);
            this.removeChild(emitter, true);
        },

        /**
         * @public
         * @method addAttractor
         * @param {CGSGPosition} position
         * @param {Number} strength
         * @param {Number} distance
         * @return {Object}
         */
        addAttractor: function (position, strength, distance) {
            var attractor = {
                position: position,
                strength: strength,
                distance: distance
            };
            this.attractors.push(attractor);
            return attractor;
        },

        /**
         * @public
         * @method removeAttractor
         * @param {Object} attractor
         */
        removeAttractor: function (attractor) {
            this.attractors.without(attractor);
        },

        /**
         * @public
         * @method addRepulsor
         * @param {CGSGPosition} position
         * @param {Number} strength
         * @param {Number} distance
         * @return {Object}
         */
        addRepulsor: function (position, strength, distance) {
            var repulsor = {
                position: position,
                strength: strength,
                distance: distance
            };
            this.repulsors.push(repulsor);
            return repulsor;
        },

        /**
         * @public
         * @method removeRepulsor
         * @param {Object} repulsor
         */
        removeRepulsor: function (repulsor) {
            this.repulsors.without(repulsor);
        },

        /**
         * override the CGSGNode &#x27;pickNode&#x27; method to return null due to performance
         * @protected
         * @method pickNode
         * @param mousePosition
         * @param absoluteScale
         * @param ghostContext
         * @param recursively
         * @param condition
         * @return {*}
         */
        pickNode: function (mousePosition, absoluteScale, ghostContext, recursively, condition) {
            return null;
        },

        /**
         * @public
         * @method copy
         * @todo : fill the method
         * @return {CGSGParticleSystem}
         */
        copy: function () {
            var node = new CGSGParticleSystem();
            node = this._super(node);

            return node;
        }
    }
);
    </pre>
</div>

                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="../assets/js/yui-prettify.js"></script>
<script src="../assets/../api.js"></script>
<script src="../assets/js/api-filter.js"></script>
<script src="../assets/js/api-list.js"></script>
<script src="../assets/js/api-search.js"></script>
<script src="../assets/js/apidocs.js"></script>
</body>
</html>
